#include "BasicBlock.hpp"
#include "Constant.hpp"
#include "Function.hpp"
#include "IRBuilder.hpp"
#include "Module.hpp"
#include "Type.hpp"

#include <iostream>
#include <memory>
// 定义一个从常数值获取/创建 ConstantInt 类实例化的宏，方便多次调用
#define CONST_INT(num) \
    ConstantInt::get(num, module)

// 定义一个从常数值获取/创建 ConstantFP 类实例化的宏，方便多次调用
#define CONST_FP(num) \
    ConstantFP::get(num, module)

int main() {
   auto module = new Module();
   auto builder = new IRBuilder(nullptr, module);
   Type *Int32Type = module->get_int32_type(); //int32类型
   //a数组用的长度为10，每个类型为int32的数组类型
   auto *arrayType = ArrayType::get(Int32Type, 10);
   //main函数
   auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module);
   // 创建 main 函数的起始 bb
   auto bb = BasicBlock::create(module, "entry", mainFun);
   // 将辅助类实例化 builder 插入指令的起始位置设置在 bb 对应的 BasicBlock
   builder->set_insert_point(bb);
   // 用 builder 创建 alloca 指令，为函数返回值分配空间
   auto retAlloca = builder->create_alloca(Int32Type);
   // main 函数默认 ret 0
   builder->create_store(CONST_INT(0), retAlloca);
   //创建a数组，给其分配空间
   auto aAlloca = builder->create_alloca(arrayType);
   auto a0GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(0)});// a[0]
   builder->create_store(CONST_INT(10), a0GEP);// a[0]=10
   auto a0Load = builder->create_load(a0GEP);// 更新后的a[0]
   auto mul = builder->create_imul(CONST_INT(2), a0Load);// a[0]*2
   auto a1GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(1)});// a[1]
   builder->create_store(mul, a1GEP);// a[1]=a[0]*2
   auto a1Load = builder->create_load(a1GEP);// 更新后的a[1]
   builder->create_ret(a1Load);// return a[1]
   std::cout << module->print();// 输出 module 中的所有 IR 指令
   delete module;
   delete builder;
   return 0;

}
